package com.wang.utils;

import com.wang.interfaces.Msg;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*;

@Slf4j
public class ClassUtil {

    /**
     * 获取包下所有类
     */
    public static List<String> getClassNameByPackage(String path) {
        List<String> className = new ArrayList<>();
        File file = new File(path);
        File[] files = file.listFiles();
        for (File f : Objects.requireNonNull(files)) {
            if (f.isDirectory()) {
                className.addAll(getClassNameByPackage(f.getPath()));
            } else {
                String cp = f.getPath();
                if (cp.endsWith(".class")) {
                    cp = cp.substring(cp.indexOf("\\com") + 1, cp.lastIndexOf("."));
                    cp = cp.replace("\\", ".");
                    className.add(cp);
                }
            }
        }
        return className;
    }

    /**
     * 通过属性名获取对象中该属性的值
     */
    public static Object getFieldValueByName(Object o, String fieldName) {
        if ("serialVersionUID".equals(fieldName)) return null;
        try {
            String firstLetter = fieldName.substring(0, 1).toUpperCase();
            String getter = "get" + firstLetter + fieldName.substring(1);
            Method method = o.getClass().getMethod(getter);
            return method.invoke(o);
        } catch (Exception e) {
            log.error("get field value by name error: ", e);
        }
        return null;
    }

    /**
     * 获得实体类的 非空键值对
     */
    public static Map<String, String> getMap(Object entity) {
        Map<String, String> map = new HashMap<>();
        Field[] fields = entity.getClass().getDeclaredFields();
        Arrays.stream(fields).forEach(field -> {
            String name = field.getName();
            String fieldValue = (String) getFieldValueByName(entity, name);
            if (Utils.isNotEmpty(fieldValue)) {
                map.put(name, fieldValue);
            }
        });
        return map;
    }

    /**
     * 获取泛型参数的实际类型
     *
     * @param clazz 抽象类
     * @return 泛型参数的实际类型
     */
    @SuppressWarnings("unchecked")
    public static Class<Msg> getActualTypeArgument(Class<?> clazz) {
        // 获取当前类的泛型父类
        Type genericSuperclass = clazz.getGenericSuperclass();
        // 循环遍历父类直到找到参数化类型
        while (genericSuperclass != null) {
            // 检查是否是参数化类型
            if (genericSuperclass instanceof ParameterizedType) {
                // 强制转换为参数化类型
                ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass;
                // 获取实际的类型参数数组
                Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
                // 检查是否有类型参数且第一个参数是Class类型
                if (actualTypeArguments.length > 0 && actualTypeArguments[0] instanceof Class<?>) {
                    // 返回第一个类型参数并强制转换为Msg类型
                    return (Class<Msg>) actualTypeArguments[0];
                }
            }
            // 检查是否是Class类型
            if (genericSuperclass instanceof Class) {
                // 继续获取父类的泛型父类
                genericSuperclass = ((Class<?>) genericSuperclass).getGenericSuperclass();
            } else {
                // 不是Class类型则退出循环
                break;
            }
        }
        // 没有找到则返回null
        return null;
    }
}
